/*
 * Copyright (c) 2001, 2002 Boris Pruessmann and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v0.5
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors:
 *    Boris Pruessmann - Initial implementation.
 * 	  David Corbin - added method to construct full path name
 */
package net.sourceforge.perforce.core.resources;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import net.sourceforge.perforce.core.PerforceCorePlugin;
import net.sourceforge.perforce.core.PerforceException;
import net.sourceforge.perforce.core.api.IPerforceServer;
import net.sourceforge.perforce.core.api.IWhereResult;
import net.sourceforge.perforce.core.internal.Policy;
import net.sourceforge.perforce.core.syncinfo.FolderSyncInfo;
import net.sourceforge.perforce.core.syncinfo.ResourceSyncInfo;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.team.core.sync.IRemoteResource;

/**
  * @version $Revision: 46 $
  * @author  <a href="mailto:bpruessmann@users.sourceforge.net">Boris Pruessmann</a>
  * @author  <a href="mailto:dcorbin@users.sourceforge.net">David Corbin</a>
  */
public class RemoteFolder extends RemoteResource
{
	// --------------------------------------------------------------------------- Private Variables
	
	/** Stores the FolderSyncInfo. */
	private FolderSyncInfo folderSyncInfo;
	/** Stores the revision. */
	private String revision;
	
	// ------------------------------------------------------------------------- Public Constructors
	
	/** Constructor for RemoteFolder.
	  *
	  * @param server the perforce server.
	  * @param parent the parent folder.
	  * @param folderSyncInfo the sync info.
	  * @param revision the revision
	  */
	public RemoteFolder(
		IPerforceServer server, RemoteFolder parent, FolderSyncInfo folderSyncInfo, String revision)
	{
		Policy.assertNotNull(folderSyncInfo);
		
		setParent(parent);
		setServer(server);
		
		this.folderSyncInfo = folderSyncInfo;
		this.revision = revision;
	}
	
	// ------------------------------------------------------------------------------ Public Methods
	
	/** @see net.sourceforge.perforce.core.resources.RemoteResource#getDepotFilename() */
	public String getDepotFilename() 
	{
		return folderSyncInfo.getDepotFileName();
	}
	
	/** @see IPerforceServer#find(String, IProgressMonitor) */
	public RemoteResource find(String name, IProgressMonitor monitor) 
		throws PerforceException 
	{
		if (name.equals(getDepotFilename()))
		{
			return this;
		}

		RemoteResource[] children = (RemoteResource[]) members(monitor);
		for (int i = 0, length = children.length; i < length; i++)
		{
			if (name.startsWith(children[i].getDepotFilename()))
			{
				return children[i].find(name, monitor);
			}
		}		
		
		return null;
	}	
	
	/** Gets the name.
	  * 
	  * @return Returns a String
	  */
	public String getName()
	{
		// XXX TODO: getName in IRemoteResource should only return the name part.
		if (getParent() == null)
		{
			return folderSyncInfo.getDepotFileName();
		}
		else
		{
			return folderSyncInfo.getDepotFileName().substring(
				getParent().folderSyncInfo.getDepotFileName().length() + 1);
		}
	}
	
	/** Returns the location.
	  * 
	  * @return the location.
	  */
	public IPath getLocation()
	{
		try
		{
			// XXX "/ " is a workaround for p4 where problem.
			String localPath = 
				getServer().where(folderSyncInfo.getDepotFileName() + "/ ").getLocalFilename(); 

			return new Path(localPath.substring(0, localPath.length() - 2));
		}
		catch (PerforceException e)
		{
			PerforceCorePlugin.log(e.getStatus());
			return null;
		}
	}

	/** Returns the contained folders.
	  * 
	  * @param monitor the monitor
	  * @return contained folders.
	  */
	public RemoteFolder[] getFolders(IProgressMonitor monitor)
	{
		try 
		{
			FolderSyncInfo[] subFolders = 
				getServer().dirs(folderSyncInfo.getDepotFileName() + "/*", monitor);
			
			RemoteFolder[] result = new RemoteFolder[subFolders.length];
			for (int i = 0; i < subFolders.length; i++)
			{
				result[i] = new RemoteFolder(getServer(), this, subFolders[i], revision);
			}
			
			return result;
		} 
		catch (PerforceException e)
		{
			PerforceCorePlugin.log(e.getStatus())	;
		}
		
		return new RemoteFolder[0];
	}
	
	/** Returns the contained files.
	  * 
	  * @param monitor the monitor
	  * @return the contained files.
	  */
	public RemoteFile[] getFiles(IProgressMonitor monitor)
	{
		try
		{
			ResourceSyncInfo[] files = 
				getServer().fstat(folderSyncInfo.getDepotFileName() + "/*", monitor);
			
			List result = new ArrayList();
			for (int i = 0; i < files.length; i++)
			{
				result.add(new RemoteFile(getServer(), files[i].getDepotFileName(), revision));
			}
			
			return (RemoteFile[]) result.toArray(new RemoteFile[0]);
		}
		catch (PerforceException e)
		{
			PerforceCorePlugin.log(e.getStatus());
		}
		
		return new RemoteFile[0];
	}
	
	/** @see IRemoteResource#getContents(IProgressMonitor) */
	public InputStream getContents(IProgressMonitor progress) 
	{
		return null;
	}

	/** @see IRemoteResource#isContainer() */
	public boolean isContainer()
	{
		return true;
	}

	/** @see RemoteResource#getSyncInfo(IProgressMonitor) */
	public ResourceSyncInfo getSyncInfo(IProgressMonitor monitor)
	{
		return null;
	}

	/** Returns the revision.
	  * 
	  * @return the revision.
	  */
	public String getRevision()
	{
		return revision;
	}

	/** @see IRemoteResource#members(IProgressMonitor) */
	public IRemoteResource[] members(IProgressMonitor monitor)
		throws PerforceException
	{
		List result = new ArrayList();
		result.addAll(Arrays.asList(getFolders(monitor)));
		result.addAll(Arrays.asList(getFiles(monitor)));
		
		return (RemoteResource[]) result.toArray(new RemoteResource[0]);
	}
	
	/** Returns the full name.
	  * 
	  * @return the full name.
	  */
	public String getFullName()
	{
		if (getParent() != null)
		{
			return getParent().getFullName() + "/" + getName();
		}
		
		return getName();
	}

	/** Sync the resource to the given revison.
	  * TODO: Wrong
	  * 
	  * @param revision the revision
	  * @param monitor for progress feedback.
	  * 
	  * @throws PerforceException in case of an error.
	  */
	public void sync(String revision, IProgressMonitor monitor)
		throws PerforceException
	{
		IWhereResult whereResult = 
			getServer().where(folderSyncInfo.getDepotFileName());
		
		String spec =
			whereResult.getClientFilename() + "/...";
		
		getServer().sync(spec, revision, monitor);		
	}
}
